#include "mcu_init.h"
#include "tos_k.h"
#include "mqttclient.h"
#include "cJSON.h"
#include "sal_module_wrapper.h"
#include "mqtt_config.h"
#include "E53_ST1.h"
#include "m26.h"


k_event_t report_result_event;
k_event_flag_t report_success = 1 << 0;
k_event_flag_t report_fail = 1 << 1;


static char is_beep_switch_changed = 1;
static char is_client_token_received = 0;


int beep_switch_cache = 0;
char client_token_cache[128] = { 0 };

/***************************************************************
* 函数名称: iot_explorer_handle_beep_switch
* 说    明: 根据power switch控制开关
***************************************************************/
static void iot_explorer_handle_beep_switch(int beep_switch)
{
    beep_switch_cache = beep_switch;

    if (0 == beep_switch) {
        if (BEEP_IS_OPEN) {
            printf("iot-explorer close the beep\r\n");
            E53_ST1_Beep_Set(OFF);
            is_beep_switch_changed = 1;
        } else {
            printf("the beep already closed\r\n");
        }
    } else {
        if (BEEP_IS_OPEN) {
            printf("the beep already opened\r\n");
        } else {
            printf("iot-explorer open the beep\r\n");
            E53_ST1_Beep_Set(ON);
            is_beep_switch_changed = 1;
        }
    }
}

/***************************************************************
* 函数名称: tos_topic_handler
* 说    明: IoT Explorer下行数据处理
***************************************************************/
static void tos_topic_handler(void* client, message_data_t* msg)
{
    cJSON *root;
    cJSON *params;
    cJSON *token;
    cJSON *method;
    cJSON *beep_switch;
    cJSON* cjson_status = NULL;
    char* status = NULL;
    k_event_flag_t event_flag = report_fail;

    /* 打印日志 */
    MQTT_LOG_I("-----------------------------------------------------------------------------------");
    MQTT_LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__,
            msg->topic_name, msg->message->qos, (char*)msg->message->payload);
    MQTT_LOG_I("-----------------------------------------------------------------------------------\n");

    // 1. 解析从云端收到的控制信息，示例控制信息为
    //"{"method":"control","clientToken":"clientToken-Xx-N_enad","params":{"power_switch":0}}"
    root = cJSON_Parse((char*)msg->message->payload);
    if (root == NULL) {
        printf("report reply message parser fail\r\n");
        cJSON_Delete(root);
        return;
    }

    // 2. 解析出method
    method = cJSON_GetObjectItem(root, "method");
    if (!method) {
        printf("Invalid json method\r\n");
        cJSON_Delete(root);
        return;
    }

    // 3. 仅处理云端下发的 control 数据
    if (0 == strncmp(method->valuestring, "control", sizeof("control") - 1)) {

        // 4. 解析出params
        params = cJSON_GetObjectItem(root, "params");
        if (params) {
        // 5. 解析出 开关指令
            beep_switch = cJSON_GetObjectItem(params, "beep_switch");
            // 根据 beep_switch 控制实际硬件开关
            if (beep_switch) {
                iot_explorer_handle_beep_switch(beep_switch->valueint);
            }
        }
        // 6. 设置clientToken回复
        token = cJSON_GetObjectItem(root, "clientToken");
        if (token) {
            strcpy(client_token_cache, token->valuestring);
            is_client_token_received = 1;
        }
        cJSON_Delete(root);
        return;
    }

    // 6. 解析出数据上报后平台回复的上报状态
    cjson_status = cJSON_GetObjectItem(root, "status");
    if (cjson_status) {
        // 7. 获取上报状态，判断上报成功或失败
        status = cJSON_GetStringValue(cjson_status);
        if (status == NULL) {
            printf("report reply status parser fail\r\n");
            event_flag = report_fail;
        } else {
            if (strstr(status, "success")) {
                event_flag = report_success;
            } else {
                event_flag = report_fail;
            }
        }
        cJSON_Delete(root);
        root = NULL;
        status = NULL;
        // 8. 触发事件
        tos_event_post(&report_result_event, event_flag);
        return;
    }
}


#define REPORT_MOTOR_DATA_TEMPLATE  "{\"method\":\"report\",\"clientToken\":\"00000001\",\"params\":{\"beep_switch\":%d}}"
#define REPORT_SENSOR_DATA_TEMPLATE "{\"method\":\"report\",\"clientToken\":\"00000001\",\"params\":{\"GPS_Info\":{\"longtitude\":%.5f,\"latitude\":%.5f}}}"
#define CONTROL_REPLY_DATA_TEMPLATE "{\"method\":\"control_reply\",\"clientToken\":\"%s\",\"code\":0,\"status\":\"ok\"}"

char report_buf[200];

/***************************************************************
* 函数名称: mqttclient_task
* 说    明: 主任务，连接平台以及发送上行数据
***************************************************************/
void mqttclient_task(void)
{
    int error;

    mqtt_client_t *client = NULL;

    mqtt_message_t msg;

    k_event_flag_t match_flag;

    E53_ST1_Data data;
    char display_longitude[20] = { 0 };
    char display_latitude[20] = { 0 };

    char  host_ip[20];

    memset(&msg, 0, sizeof(msg));

    m26_sal_init(HAL_UART_PORT_0);

    mqtt_log_init();

    client = mqtt_lease();

    tos_event_create(&report_result_event, (k_event_flag_t)0u);

    /* Domain Format: <your product ID>.iotcloud.tencentdevices.com */
    tos_sal_module_parse_domain(MQTT_SERVER_DOMAIN, host_ip, sizeof(host_ip));
    /*
        These infomation is generated by mqtt_config_gen.py tool in "TencentOS-tiny\tools" directory.
    */
    mqtt_set_port(client, MQTT_SERVER_PORT);
    mqtt_set_host(client, host_ip);
    mqtt_set_client_id(client, MQTT_CLIENT_ID);
    mqtt_set_user_name(client, MQTT_USR_NAME);
    mqtt_set_password(client, MQTT_PASSWORD);
    mqtt_set_clean_session(client, 1);

    error = mqtt_connect(client);

    MQTT_LOG_D("mqtt connect error is %#0x", error);

    error = mqtt_subscribe(client, MQTT_SUBSCRIBE_TOPIC_DOWN, QOS0, tos_topic_handler);

    MQTT_LOG_D("mqtt subscribe error is %#0x", error);

    while (1) {

        /* 上报传感器数据 */
        E53_ST1_Read_Data(&data);
        sprintf(display_longitude, "Longitude:%.5f     ", data.Longitude);
        LCD_ShowCharStr(10, 100, display_longitude, WHITE, BLUE, 24);
        sprintf(display_latitude, "Latitude:%.5f    ", data.Latitude);
        LCD_ShowCharStr(10, 140, display_latitude, WHITE, BLUE, 24);
        if (data.Longitude != 0 && data.Latitude != 0) {
            memset(&msg, 0, sizeof(msg));
            memset(report_buf, 0, sizeof(report_buf));
            snprintf(report_buf, sizeof(report_buf), REPORT_SENSOR_DATA_TEMPLATE, data.Longitude, data.Latitude);
            msg.qos = QOS0;
            msg.payload = (void *)report_buf;
            error = mqtt_publish(client, MQTT_PUBLISH_TOPIC_UP, &msg);
            MQTT_LOG_D("mqtt publish error is %#0x", error);
            tos_event_pend(&report_result_event,
                        report_success | report_fail,
                        &match_flag,
                        TOS_TIME_FOREVER,
                        TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_CLR);

            if (match_flag == report_success) {
                printf("report to Tencent IoT Explorer success\r\n");

            } else if (match_flag == report_fail) {
                printf("report to Tencent IoT Explorer fail\r\n");
            }
        }
        /* END*/

        /* 如果蜂鸣器状态发生改变，则蜂鸣器电机的状态 */
        if (is_beep_switch_changed) {
            is_beep_switch_changed = 0;
            memset(&msg, 0, sizeof(msg));
            memset(report_buf, 0, sizeof(report_buf));
            snprintf(report_buf, sizeof(report_buf), REPORT_MOTOR_DATA_TEMPLATE, beep_switch_cache);
            msg.qos = QOS0;
            msg.payload = (void *)report_buf;
            error = mqtt_publish(client, MQTT_PUBLISH_TOPIC_UP, &msg);

            MQTT_LOG_D("mqtt publish error is %#0x", error);
            tos_event_pend(&report_result_event,
                       report_success | report_fail,
                       &match_flag,
                       TOS_TIME_FOREVER,
                       TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_CLR);

            if (match_flag == report_success) {
                printf("report to Tencent IoT Explorer success\r\n");

            } else if (match_flag == report_fail) {
                printf("report to Tencent IoT Explorer fail\r\n");
            }
        }
        /* END*/
        
        /* 接受到下行control消息，回复最近一条 */
        if (is_client_token_received) {
        	is_client_token_received = 0;
            memset(&msg, 0, sizeof(msg));
            memset(report_buf, 0, sizeof(report_buf));
            snprintf(report_buf, sizeof(report_buf), CONTROL_REPLY_DATA_TEMPLATE, client_token_cache);
            msg.qos = QOS0;
            msg.payload = (void *) report_buf;
            error = mqtt_publish(client, MQTT_PUBLISH_TOPIC_UP, &msg);

            MQTT_LOG_D("mqtt publish error is %#0x", error);
        }
        /* END*/
        
        tos_task_delay(5000);
    }
}

/***************************************************************
* 函数名称: application_entry
* 说    明: 应用入口
***************************************************************/
void application_entry(void *arg)
{
    E53_ST1_Init();
    mqttclient_task();
    while (1) {
        printf("This is a mqtt demo!\r\n");
        tos_task_delay(1000);
    }
}
